<?php

/**
 * descript:
 * User: blue
 * Date: 2018/5/31 11:05
 */

namespace app\api\service;

use app\api\model\Order as OrderModel;
use app\api\model\OrderProduct;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\exception\OrderException;
use app\lib\exception\ParamException;
use app\lib\exception\ProductException;
use app\lib\exception\UserException;
use think\Db;

class Order
{

    private $uid;
    private $sProducts;
    private $dProducts;

    /**
     * 下订单
     * @param $uid
     * @param $sProducts
     */
    public function Place($uid,$sProducts){
        $this->uid=$uid;
        $this->sProducts=$sProducts;
        $this->dProducts=$this->getProductsByOrder($sProducts);
        $status=$this->getOrderStatus();
        //成功失败返回的状态码是不一样的
        if(!$status['pass']){
            $status['order_id']=-1;
            return $status;
        }
        $snapOrder=$this->snapOrder($status);
        $status=$this->createOrder($snapOrder);
        $status['pass']=true;
        return $status;
    }

    /**
     * 获取订单库存状态的public函数
     * 根据order_id组合$sProducts--->$dProducts两个成员属性数据,然后调用getOrderStatues
     */
    public function getOrderStock($id){
        $data=OrderProduct::all(['order_id'=>$id])->visible(["product_id","count"])->toArray();
        if(empty($data)){
            throw new OrderException();
        }
        $this->sProducts=$data;
        $this->dProducts=$this->getProductsByOrder($this->sProducts);
        $status=$this->getOrderStatus();
        return $status;
    }
    /**
     * 获取订单状态
     * @param $sProducts 订单数据
     * @return array  $oStatus=[
                    * 'pass'=>true,
                    * 'orderPrice'=>0,
                    * 'pStatusArray'=>[]
                    * ];
     * @throws ParamException
     */
    private function getOrderStatus(){
        $oStatus=[
            'pass'=>true,
            'orderPrice'=>0,
            'pStatusArray'=>[],
            'totalCount'=>0
        ];
        //循环订单数组
        foreach ($this->sProducts as $sProduct){
            $pStatus=$this->getProductStatus($sProduct['product_id'],$sProduct['count'],$this->dProducts);
            //只要一件商品库存量不足,就将pass设为false;
            if(!$pStatus['haveStock']){
                $oStatus['pass']=false;
            }
            //将订单信息压入pStatusArray
            array_push($oStatus['pStatusArray'],$pStatus);
            //计算订单总价
            $oStatus['orderPrice']=$pStatus['totalPrice']+$oStatus['orderPrice'];
            $oStatus['totalCount']+=$pStatus['count'];

        }
        return $oStatus;
    }

    /**
     * 商品库存量检测
     * @param $sPID 商品id
     * @param $sCount 商品数量
     * @param $dProducts 数据库中的商品数组
     * @return array $pStatus=[
                    'id'=>null,
                    'haveStock'=>false,
                    'count'=>0,
                    'name'=>'',
                    'totalPrice'=>0
                    ];
     * @throws ParamException
     */
    private function getProductStatus($sPID,$sCount,$dProducts){
        //sPID对应$dproducts的索引
        $index=-1;
        $pStatus=[
          'id'=>null,
          'haveStock'=>false,
          'count'=>0,
          'name'=>'',
          'totalPrice'=>0
        ];
    //    循环数据库中的商品数组,和订单中的传来的数据进行比较
        for($i=0;$i<count($dProducts);$i++){
            if($sPID==$dProducts[$i]['id']){
                $index=$i;
            }
        }
        if($index==-1){
            throw new ParamException(['msg'=>'id号为'.$pStatus['id'].'订单商品不存在']);
        }else{
            $pStatus['id']=$dProducts[$index]['id'];
            $pStatus['name']=$dProducts[$index]['name'];
            $pStatus['count']=$sCount;
            if($dProducts[$index]['stock']-$sCount>0){
                $pStatus['haveStock']=true;
            }
            $pStatus['totalPrice']=$dProducts[$index]['price']*$sCount;
        }
        return $pStatus;
    }

    /**
     * 根据订单查找真实商品
     * @param $sProducts
     *
     */
    private function getProductsByOrder($sProducts){
        $ids=[];
        //重组订单的商品数组 进行数据库查询
        foreach ($sProducts as $sProduct){
           array_push($ids,$sProduct['product_id']);
        }
        $dProducts=Product::all($ids)->visible(['id','price','stock','name','main_img_url'])->toArray();
        if(empty($dProducts)){
            throw new ProductException();
        }
        return $dProducts;
    }
    //生成订单快照
    private function snapOrder($status){

        $address=json_encode($this->getAddress(),JSON_UNESCAPED_UNICODE);
        $snap=[
            'snap_img'=>$this->dProducts[0]['main_img_url'],
            'snap_name'=>$this->dProducts[0]['name'],
            'total_count'=>$status['totalCount'],
            'snap_items'=>json_encode($status['pStatusArray'],JSON_UNESCAPED_UNICODE),
            'snap_address'=>$address,
            'orderPrice'=>$status['orderPrice'],
        ];
        //多件商品name加等
        if(count($this->dProducts)>1){
            $snap['snap_name']=$snap['snap_name']."等";
        }
        return $snap;
    }

    /**
     * 新建订单
     * @param $snap
     */
    private function createOrder($snap){
        Db::startTrans();
        try{
            //生成订单,保存到数据表
            $order_no=$this->makeOrderNo();
            $order=new OrderModel();
            $order->order_no=$order_no;
            $order->user_id=$this->uid;
            $order->total_price=$snap['orderPrice'];
            $order->snap_img=$snap['snap_img'];
            $order->snap_name=$snap['snap_name'];
            $order->snap_address=$snap['snap_address'];
            $order->snap_items=$snap['snap_items'];
            $order->save();
            //保存到Order_Product表中
            $id=$order->id;
            $create_time=$order->create_time;
            $arr=$this->sProducts;
            array_walk($arr,function(&$v,$k) use($id){
                $v['order_id']=$id;
            });
            (new OrderProduct())->saveAll($arr);
            Db::commit();
            return[
              'order_no'=>$order_no,
              'order_id'=>$id,
              'create_time'=>$create_time,
            ];
        }catch (\Exception $e){
            Db::rollback();
            throw $e;
        }
    }
    /**
     * 生成订单编号
     * @return string
     */
    public  function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn =
            $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        return $orderSn;
    }
    //获取地址
    private function getAddress(){
        $data=UserAddress::where('user_id','=',$this->uid)->find();
        if(empty($data)){
            throw new UserException(['msg'=>'用户地址不存在']);
        }
        return $data;
    }

    /**
     * 获取订单库存状态的改良方法
     * 根据order_id组合$sProducts--->$dProducts两个成员属性数据,然后调用getOrderStatues
     */
    public function OrderStock( $arr){
        $data=OrderProduct::where('order_no','=',$arr)->find()->visible(["product_id","count"]);
        if(!empty($data)){
            $data=$data->toArray();
        }
        if(empty($data)){
            throw new OrderException();
        }
        $this->sProducts=$data;
        $this->dProducts=$this->getProductsByOrder($this->sProducts);
        $status=$this->getOrderStatus();
        return $status;
    }
}